/*
author:杨文超
email:yangwenchao@keynection.cn
Data Circuit-Terminating Equipment 数据线路端接设备，modem
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include "esp_types.h"
#include "esp_err.h"
#include "geminai_modem.h"
#include "geminai_modem_dte.h"

/*
Forward declaration of the command list object, which (if enabled) is used
to populate a command palette and access commands by its symbolic name
*/
struct esp_modem_dce_cmd_list;

/*
Working state of DCE
*/
typedef enum {
    ESP_MODEM_STATE_PROCESSING, /* In processing */
    ESP_MODEM_STATE_SUCCESS,    /* Process successfully */
    ESP_MODEM_STATE_FAIL        /* Process failed */
} esp_modem_state_t;

/*
Generic command type used in DCE unit
*/
typedef esp_err_t (*dce_command_t)(esp_modem_dce_t *dce, void *param, void *result);

/*
Type of line handlers called from DTE upon line response reception
*/
typedef esp_err_t (*esp_modem_dce_handle_line_t)(esp_modem_dce_t *dce, const char *line);

/*
DCE(Data Communication Equipment)对象结构体

*/
struct esp_modem_dce {
    esp_modem_state_t state;                                                    /* Modem working state */
    esp_modem_mode_t mode;                                                      /* Working mode */
    esp_modem_dte_t *dte;                                                       /* DTE which connect to DCE */
    struct esp_modem_dce_cmd_list *dce_cmd_list;
    esp_modem_dce_config_t config;
    esp_modem_dce_handle_line_t handle_line;                                    /* Handle line strategy */

    void *handle_line_ctx;                                                      /* DCE context reserved for handle_line processing */
    // higher level actions DCE unit can take
    esp_err_t (*set_working_mode)(esp_modem_dce_t *dce, esp_modem_mode_t mode); /* Set working mode */
    esp_err_t (*deinit)(esp_modem_dce_t *dce);                                  /* Destroys the DCE */
    esp_err_t (*start_up)(esp_modem_dce_t *dce);                                /* Start-up sequence */

    // list of essential commands for esp-modem basic work
    dce_command_t hang_up;                                                      /* generic command for hang-up */
    dce_command_t set_pdp_context;                                              /* generic command for pdp context */
    dce_command_t set_data_mode;                                                /* generic command for data mode */
    dce_command_t resume_data_mode;                                             /* generic command to resume already dialed data mode */
    dce_command_t set_command_mode;                                             /* generic command for command mode */
    dce_command_t set_echo;                                                     /* generic command for echo mode */
    dce_command_t sync;                                                         /* generic command for sync */
    dce_command_t set_flow_ctrl;                                                /* generic command for flow-ctrl */
    dce_command_t store_profile;                                                /* generic command for store-profile */
};

/*
Sending generic command to DCE

@param[in] dce     Modem DCE object
@param[in] command String command
@param[in] timeout Command timeout in ms
@param[in] handle_line Function ptr which processes the command response
@param[in] ctx         Function ptr context

@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
     - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_dce_generic_command(esp_modem_dce_t *dce, const char * command, uint32_t timeout, esp_modem_dce_handle_line_t handle_line, void *ctx);

/*
Indicate that processing current command has done

@param dce Modem DCE object
@param state Modem state after processing
@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_process_command_done(esp_modem_dce_t *dce, esp_modem_state_t state);

/*
Default handler for response
Some responses for command are simple, commonly will return OK when succeed of ERROR when failed

@param dce Modem DCE object
@param line line string
@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_handle_response_default(esp_modem_dce_t *dce, const char *line);

/*
Set Working Mode

@param dce Modem DCE object
@param mode working mode

@return esp_err_t
    - ESP_OK on success
    - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_working_mode(esp_modem_dce_t *dce, esp_modem_mode_t mode);

/*
Default start-up sequence, which sets the modem into an operational mode

@param dce Modem DCE object

@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_default_start_up(esp_modem_dce_t *dce);

/*
Destroys the DCE

@param dce Modem DCE object

@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_default_destroy(esp_modem_dce_t *dce);

/*
Initializes the DCE

@param dce Modem DCE object
@param config DCE configuration structure

@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_default_init(esp_modem_dce_t *dce, esp_modem_dce_config_t* config);

/*
Sets the DCE parameters. This API updates runtime DCE config parameters,
typically used to update PDP context data.

@param dce Modem DCE object
@param config DCE configuration structure

@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_params(esp_modem_dce_t *dce, esp_modem_dce_config_t* config);

/*
Change PDP context APN, will takes effect after redial-up, redial-up will execute if force_enable is true,

@param dce Modem DCE object
@param new_apn Access point name
@param force_enable if force enable
@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
*/
esp_err_t esp_modem_dce_set_apn(esp_modem_dce_t *dce, const char *new_apn);

/*
Executes a specific command from the list

@param dce       Modem DCE object
@param command   Symbolic name of the command to execute
@param param     Generic parameter to the command
@param result    Generic output parameter

@return esp_err_t
     - ESP_OK on success
     - ESP_FAIL on error
     - ESP_ERR_TIMEOUT if timeout while waiting for expected response
*/
esp_err_t esp_modem_command_list_run(esp_modem_dce_t *dce, const char * command, void * param, void* result);

/*
Deinitialize the command list

@param dce       Modem DCE object

*/
esp_err_t esp_modem_command_list_deinit(esp_modem_dce_t *dce);

/*
Initializes default command list with predefined command palette
@param dce       Modem DCE object
@return ESP_OK on success, ESP_FAIL on error
*/
esp_err_t esp_modem_set_default_command_list(esp_modem_dce_t *dce);

/*
Add or set specific command to the command list

@param dce        Modem DCE object
@param command_id Command symbolic name
@param command    Generic command function pointer

@return ESP_OK on success, ESP_FAIL on error
*/
esp_err_t esp_modem_command_list_set_cmd(esp_modem_dce_t *dce, const char * command_id, dce_command_t command);

#ifdef __cplusplus
}
#endif
